package com.john.utils.common;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.RandomStringUtils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串处理及转换工具类 
 */
public class StringUtil {
	private static Pattern humpPattern = Pattern.compile("[A-Z]");
	private static Pattern linePattern = Pattern.compile("_(\\w)");

	public static void main(String[] args) {
		// System.out.println(isIntegerType("404"));
		System.out.println(random(32,false));
	}

	/**
	 * 过滤emoji 或者 其他非文字类型的字符
	 * @param source
	 * @return
	 */
	public static String filterEmoji(String source) {
		int len = source.length();
		StringBuilder buf = new StringBuilder(len);
		for (int i = 0; i < len; i++) {
			char codePoint = source.charAt(i);
			if (isNotEmojiCharacter(codePoint)) {
				buf.append(codePoint);
			}
		}
		return replaceEmoji(buf.toString());
	}

	/**
	 * 是否json
	 * @param string
	 * @return
	 */
	public static boolean isJson(String string) {
		try {
			JSONObject jsonStr = JSONObject.parseObject(string);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 判断一个字符串是否为url
	 * @param str String 字符串
	 * @return boolean 是否为url
	 * @author peng1 chen
	 * **/
	public static boolean isURL(String str){
		//转换为小写
		str = str.toLowerCase();
		String regex = "^((https|http|ftp|rtsp|mms)?://)"  //https、http、ftp、rtsp、mms
				+ "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?" //ftp的user@
				+ "(([0-9]{1,3}\\.){3}[0-9]{1,3}" // IP形式的URL- 例如：199.194.52.184
				+ "|" // 允许IP和DOMAIN（域名）
				+ "([0-9a-z_!~*'()-]+\\.)*" // 域名- www.
				+ "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\\." // 二级域名
				+ "[a-z]{2,6})" // first level domain- .com or .museum
				+ "(:[0-9]{1,5})?" // 端口号最大为65535,5位数
				+ "((/?)|" // a slash isn't required if there is no file name
				+ "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
		return  str.matches(regex);
	}


	/**
	 * 判断某个字符串是否是一个 IP 地址
	 * @param str 字符串
	 */
	public static boolean isIpStr(String str) {
		if (str.length() < 7 || str.length() > 15 || "".equals(str)){
			return false;
		}
		String regex = "\\.";
		// 包含分隔符 且 个数正确
		if (str.contains(".") && str.split(regex).length > 0) {
			boolean legalNumber = true;
			// 四个全部是数字，且都在合理的范围内
			for (String obj : Arrays.asList(str.split(regex))) {
				if (isIntegerType(obj)) {
					Integer value = Integer.parseInt(obj);
					legalNumber = isNumberBetween(value, 0, 255);
				} else {
					// 任意一个不是数字，不合法
					legalNumber = false;
					break;
				}
			}
			return legalNumber;
		}
		return false;
	}

	/**
	 * 包含边界值
	 * @param number 检查值
	 * @param min 最小
	 * @param max 最大
	 */
	public static boolean isNumberBetween(Number number, Number min, Number max) {
		return number.longValue() >= min.longValue() && number.longValue() <= max.longValue();
	}

	/**
	 * 是否数字
	 * @param str
	 * @return
	 */
	public static boolean isIntegerType(String str) {
		Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
		return pattern.matcher(str).matches();
	}

	//过滤emoji
	private static boolean isNotEmojiCharacter(char codePoint) {
		return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA) || (codePoint == 0xD)
				|| ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
				|| ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
	}

	/**去除表情符号，特殊字符好*/
	private static String replaceEmoji(String str) {
		//去除表情字符
        String patternString = "[\uD83C\uDC04-\uD83C\uDE1A]|[\uD83D\uDC66-\uD83D\uDC69]|[\uD83D\uDC66\uD83C\uDFFB-\uD83D\uDC69\uD83C\uDFFF]|[\uD83D\uDE45\uD83C\uDFFB-\uD83D\uDE4F\uD83C\uDFFF]|[\uD83C\uDC00-\uD83D\uDFFF]|[\uD83E\uDD10-\uD83E\uDDC0]|[\uD83D\uDE00-\uD83D\uDE4F]|[\uD83D\uDE80-\uD83D\uDEF6]";
        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(str);
        str = matcher.replaceAll("");
        //去除特殊字符
        patternString ="[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        pattern = Pattern.compile(patternString);
        matcher = pattern.matcher(str);
        return matcher.replaceAll("");
    }

	/**
	 * 驼峰转下划线
	 * @param str
	 * @param toUpperCase 是否大写
	 * @return
	 */
	public static String humpToLine(String str,boolean toUpperCase){
		Matcher matcher = humpPattern.matcher(str);
		StringBuffer sb = new StringBuffer();
		while(matcher.find()){
			matcher.appendReplacement(sb, "_"+ matcher.group(0).toLowerCase());
		}
		matcher.appendTail(sb);
		if(toUpperCase){
			return sb.toString().substring(1).toUpperCase();
		}else{
			return sb.toString().substring(1);
		}
	}

	/**
	 * 下划线转驼峰
	 * @param str
	 * @param type 是否保留下划线
	 * @return
	 */
	public static String lineToHump(String str,boolean type){
		str = str.toLowerCase();
		Matcher matcher = linePattern.matcher(str);
		StringBuffer sb = new StringBuffer();
		while(matcher.find()){
			if(type){
				matcher.appendReplacement(sb, "_" + matcher.group(1).toUpperCase());
			}else{
				matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
			}
		}
		matcher.appendTail(sb);
		return firstUpperCase(sb.toString(),true);
	}

	/**
	 * 首字母大小写
	 * @param realName
	 * @param toUpperCase 是否大小写
	 * @return
	 */
	public static String firstUpperCase(String realName,boolean toUpperCase) {
		if(toUpperCase){
			return realName.substring(0, 1).toUpperCase() + realName.substring(1);
		}else{
			return realName.substring(0, 1).toLowerCase() + realName.substring(1);
		}
	}

	/**
	 * 随机生成指定长度字符串
	 * @param length 长度
	 * @param isNumber 是否全部数字
	 * @return
	 */
	public static String random(int length,boolean isNumber) {
		String str = "zxcvbnmlkjhgfdsaqwertyuiopQWERTYUIOPASDFGHJKLZXCVBNM1234567890";// 初始化种子
		if(isNumber){
			str = "1234567890";// 初始化种子
		}
		return RandomStringUtils.random(length, str);// 返回6位的字符串
	}

	/**
	 * 截取字符串 操作字符用指定字符代替
	 * @param subject 源字符串
	 * @param beginIndex 开始位置
	 * @param endIndex 截止位置
	 * @param symbol 代替字符
	 * @return
	 */
	public static String getLimitLengthString(String subject, int beginIndex, int endIndex, String symbol) {
		if (subject != null && subject.length() > endIndex) {
			subject = subject.substring(beginIndex, endIndex) + symbol;
		}
		return subject;
	}

	/**
	 * repeat - 根据指定次数复制原字符串
	 * @param src 原字符串
	 * @param count 重复生成次数
	 */
	public static String repeat(String src, int count) {
		StringBuffer s = new StringBuffer();
		for (int i = 0; i < count; i++)
			s.append(src);
		return s.toString();
	}


	/**
	 * 判断是否是空
	 * null or "" => true
	 */
	public static boolean isEmpty(Object object) {
		if (object != null && !object.equals("")) {
			return false;
		}
		return true;
	}

	/**
	 * 把 键=值 参数表转换成字符串
	 * 如：a=1,b=2 => a=1&b=2
	 */
	public static String mapToString(Map<String, String> map) {
		if (map != null && map.size() > 0) {
			String result = "";
			Iterator it = map.keySet().iterator();
			while (it.hasNext()) {
				String name = (String) it.next();
				String value = (String) map.get(name);
				result += (result.equals("")) ? "" : "&";
				result += String.format("%s=%s", name, value);
			}
			return result;
		}
		return null;
	}


	/**
	 * 去除字符串中的空格、回车、换行符、制表符
	 * @param str
	 * @return
	 */
	public static String strTrim(String str) {
		if (str != null) {
			Pattern p = Pattern.compile("\t|\r|\n");
			Matcher m = p.matcher(str);
			str = m.replaceAll("");
		}
		return str;
	}

	/**
	 * 除去html标签
	 * @param str 源字符串
	 */
	public static String removeHTMLLable(String str) {
		str = stringReplace(str, "<script[^>]*>[\\d\\D]*?</script>", "");// 去掉script之间的内容
		str = stringReplace(str, "<br ?/?>", "\n");// 去<br><br />
		str = stringReplace(str, "<([^<>]+)>", "");// 去掉<>内的字符
		//str = stringReplace(str, "&nbsp;", " ");// 替换空格
		str = stringReplace(str, "&(\\S)(\\S?)(\\S?)(\\S?);", "");// 去<br><br />
		return str;
	}

	/**
	 * 去掉HTML标签之外的字符串
	 * @param str 源字符串
	 */
	public static String removeOutHTMLLable(String str) {
		str = stringReplace(str, ">([^<>]+)<", "><");
		str = stringReplace(str, "^([^<>]+)<", "<");
		str = stringReplace(str, ">([^<>]+)$", ">");
		return str;
	}

	/**
	 * 字符串替换
	 * @param str 源字符串
	 * @param regEx 正则表达式样式
	 * @param sd 替换文本
	 */
	public static String stringReplace(String str, String regEx, String sd) {
		Pattern p = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(str);
		str = m.replaceAll(sd);
		return str;
	}

	/**
	 * 解析字符串返回map键值对
	 * (例：a=1&b=2 => a=1,b=2)
	 * @param query
	 *            源参数字符串
	 * @param split1
	 *            键值对之间的分隔符（例：&）
	 * @param split2
	 *            key与value之间的分隔符（例：=）
	 * @param dupLink  重复参数名的参数值之间的连接符，连接后的字符串作为该参数的参数值，可为null null：不允许重复参数名出现，则靠后的参数值会覆盖掉靠前的参数值。
	 */
	public static Map<String, String> parseQuery(String query, char split1, char split2, String dupLink) {
		if (!isEmpty(query) && query.indexOf(split2) > 0) {
			Map<String, String> result = new HashMap();

			String name = null;
			String value = null;
			String tempValue = "";
			int len = query.length();
			for (int i = 0; i < len; i++) {
				char c = query.charAt(i);
				if (c == split2) {
					value = "";
				} else if (c == split1) {
					if (!isEmpty(name) && value != null) {
						if (dupLink != null) {
							tempValue = result.get(name);
							if (tempValue != null) {
								value += dupLink + tempValue;
							}
						}
						result.put(name, value);
					}
					name = null;
					value = null;
				} else if (value != null) {
					value += c;
				} else {
					name = (name != null) ? (name + c) : "" + c;
				}
			}

			if (!isEmpty(name) && value != null) {
				if (dupLink != null) {
					tempValue = result.get(name);
					if (tempValue != null) {
						value += dupLink + tempValue;
					}
				}
				result.put(name, value);
			}

			return result;
		}
		return null;
	}

	/**
	 * 获取从start开始用指定字符替换len个长度后的字符串
	 * @param str 要替换的字符串
	 * @param start 开始位置
	 * @param len 长度
	 * @param symbol 指定字符
	 */
	public static String getMaskStr(String str, int start, int len,String symbol) {
		if (isEmpty(str)) {
			return str;
		}
		if (str.length() < start) {
			return str;
		}
		// 获取*之前的字符串
		String ret = str.substring(0, start);
		// 获取最多能打的*个数
		int strLen = str.length();
		if (strLen < start + len) {
			len = strLen - start;
		}
		// 替换成 symbol
		for (int i = 0; i < len; i++) {
			ret += symbol;
		}
		// 加上symbol之后的字符串
		if (strLen > start + len) {
			ret += str.substring(start + len);
		}
		return ret;
	}

	/**
	 * 数字金额大写转换
	 * @param number 数字
	 * @return 中文大写数字
	 */
	public static String digitUppercase(double number){
		String[] fraction = { "角", "分" };
		String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
		String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } };

		String head = number < 0 ? "负" : "";
		number = Math.abs(number);

		String s = "";
		for (int i = 0; i < fraction.length; i++) {
			s += (digit[(int) (Math.floor(number * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
		}
		if (s.length() < 1) {
			s = "整";
		}
		int integerPart = (int) Math.floor(number);

		for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
			String p = "";
			for (int j = 0; j < unit[1].length && number > 0; j++) {
				p = digit[integerPart % 10] + unit[1][j] + p;
				integerPart = integerPart / 10;
			}
			s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
		}
		return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
	}

	/**
	 * 字符替换为‘*‘号
	 * @param content 身份证号
	 * @param front  需要显示前几位
	 * @param end    需要显示末几位
	 * @param symbol 替换字符
	 * @return 处理完成之后的结果
	 */
	public static String encrypt(String content, int front, int end,String symbol) {
		if (isEmpty(content)) return content;
		if ((front + end) > content.length()) return content;
		if (front < 0 || end < 0) return content;
		//计算 ‘*’ 号数量
		int asteriskCount = content.length() - (front + end);
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < asteriskCount; i++) {
			stringBuilder.append(symbol);
		}
		String regex = "(\\w{" + String.valueOf(front) + "})(\\w+)(\\w{" + String.valueOf(end) + "})";
		return content.replaceAll(regex, "$1" + stringBuilder + "$3");
	}

}
